home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / ab20 / ab20_archive / datacomm / xpr / xprxmodem-34.3.lzh / xprxmodem.c < prev    next >
C/C++ Source or Header  |  1990-08-18  |  11KB  |  538 lines

  1. /*
  2.  * This XPR is based on bmodem - the BIX modem program
  3.  * 
  4.  * by David Betz, BYTE Magazine/BIX
  5.  * 
  6.  * bmodem consists of three files: bmodem.c, dlink.c, mdio.c. bmodem.c and
  7.  * mdio.c were substantially modified and merged into this file, xprxmodem.c
  8.  * 
  9.  * dlink.c was ANSIsized and made re-entrant for xprlib by m. boucher.
  10.  * 
  11.  * Modified substantially by W.G.J. Langeveld for use in VLT.
  12.  * 
  13.  * Transformed into XPR by Marc Boucher
  14.  * (BIX: mboucher Internet: marc@CAM.ORG)
  15.  * 
  16.  */
  17.  
  18. /* Changes:
  19.  
  20.     Version        Comments
  21.     ---------------------------------------------------------------------
  22.     34.2        SerialTransparent no longer affects 7wire handshaking
  23.     34.1        Initial Release
  24.  
  25. */
  26.  
  27. static char _StAmP[] = "Copyright ©1990 Marc Boucher, All Rights Reserved -- Compiled: " __DATE__ " " __TIME__;
  28.  
  29. #include <string.h>
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. #include <ctype.h>
  33.  
  34. #include "xprxmodem.h"
  35.  
  36. #include "proto-callback.h"
  37. #include "proto-dlink.h"
  38.  
  39. long XProtocolCleanup(struct XPR_IO * IO)
  40. {
  41.     if (IO->xpr_data) {
  42.         FreeMem(IO->xpr_data, sizeof(struct XProtocolData));
  43.         IO->xpr_data = NULL;
  44.     }
  45.     return (1);
  46. }
  47.  
  48. static char *MYstrtok(char *cmd, char *toks, char **ptr)
  49. {
  50.     char *pa;
  51.  
  52.     if (!cmd) {
  53.         cmd = *ptr;
  54.         if (!cmd)
  55.             return (NULL);
  56.     }
  57.     while (*cmd && strchr(toks, (int) *cmd))
  58.         ++cmd;
  59.  
  60.     if (!*cmd)
  61.         return (NULL);
  62.  
  63.     if (pa = strpbrk(cmd, toks))
  64.         *pa++ = 0;
  65.     *ptr = pa;
  66.     return (cmd);
  67. }
  68.  
  69. static void ParseConfigString(struct XPR_IO * IO, char *str)
  70. {
  71.     char *delim = ",";
  72.     char *tokptr;
  73.     char *dupstr, *zz;
  74.  
  75.     dupstr = AllocMem(strlen(str) + 1, MEMF_PUBLIC);
  76.     if (!dupstr)
  77.         return;
  78.  
  79.     strcpy(dupstr, str);
  80.  
  81.     zz = MYstrtok(dupstr, delim, &tokptr);
  82.  
  83.     if (zz)
  84.         do {
  85.             switch (toupper((int) *zz)) {
  86.             case 'T':
  87.                 switch (toupper((int) *(zz + 1))) {
  88.                 case '0':
  89.                     IO->xpr_data->ascii = 0;
  90.                     break;
  91.                 case '1':
  92.                     IO->xpr_data->ascii = 1;
  93.                     break;
  94.                 default:
  95.                     DisplayBeep(NULL);
  96.                     break;
  97.                 }
  98.                 break;
  99.             case 'C':
  100.                 switch (*(zz + 1)) {
  101.                 case '0':
  102.                     IO->xpr_data->crc_conf = 0;
  103.                     break;
  104.                 case '1':
  105.                     IO->xpr_data->crc_conf = 1;
  106.                     break;
  107.                 default:
  108.                     DisplayBeep(NULL);
  109.                     break;
  110.                 }
  111.                 break;
  112.             case 'K':
  113.                 switch (*(zz + 1)) {
  114.                 case '0':
  115.                     IO->xpr_data->big = 0;
  116.                     break;
  117.                 case '1':
  118.                     IO->xpr_data->big = 1;
  119.                     break;
  120.                 default:
  121.                     DisplayBeep(NULL);
  122.                     break;
  123.                 }
  124.                 break;
  125.             default:
  126.                 DisplayBeep(NULL);
  127.                 break;
  128.             }
  129.             zz = MYstrtok(0, delim, &tokptr);
  130.         } while (zz);
  131.  
  132.     FreeMem(dupstr, strlen(str) + 1);
  133. }
  134.  
  135. long XProtocolSetup(struct XPR_IO * IO)
  136. {
  137.     long (*xupdate) (), (*xgets) (), (*xoptions) () = NULL;
  138.     struct XPR_UPDATE xpru;
  139.     char buffy[128];
  140.  
  141.     if ((xupdate = IO->xpr_update) == NULL)
  142.         return (0);
  143.     if ((xgets = IO->xpr_gets) == NULL)
  144.         return (0);
  145.  
  146.     if (IO->xpr_extension >= 1)
  147.         xoptions = IO->xpr_options;
  148.  
  149.     /*
  150.      * Allocate a bit of memory for a data buffer
  151.      */
  152.     if (IO->xpr_data == NULL) {
  153.         IO->xpr_data = AllocMem(sizeof(struct XProtocolData), MEMF_PUBLIC | MEMF_CLEAR);
  154.         if (!IO->xpr_data) {
  155.             xpru.xpru_updatemask = XPRU_ERRORMSG;
  156.             xpru.xpru_errormsg = "XModem - Out of memory!";
  157.             calla(xupdate, &xpru);
  158.             return (0L);
  159.         }
  160.         IO->xpr_data->buffer = &IO->xpr_data->packet[3];
  161.     }
  162.     /* If setup string isn't handed to us, ask questions */
  163.  
  164.     if (IO->xpr_filename == NULL) {
  165.         if (xoptions) {
  166.             struct xpr_option *opti[4];
  167.  
  168.             struct xpr_option opti3 =
  169.             {"Text Mode", XPRO_BOOLEAN, NULL, 4};
  170.             struct xpr_option opti2 =
  171.             {"1K Blocks", XPRO_BOOLEAN, NULL, 4};
  172.             struct xpr_option opti1 =
  173.             {"CRC", XPRO_BOOLEAN, NULL, 4};
  174.             struct xpr_option opti0 =
  175.             {"XModem options:", XPRO_HEADER, NULL, 0};
  176.  
  177.             /* kludge because of manx aztec 5.0b stupid bug */
  178.             opti[0] = &opti0;
  179.             opti[1] = &opti1;
  180.             opti[2] = &opti2;
  181.             opti[3] = &opti3;
  182.  
  183.             opti1.xpro_value = AllocMem(4, MEMF_PUBLIC);
  184.             if (opti1.xpro_value) {
  185.                 if (IO->xpr_data->crc_conf)
  186.                     strcpy(opti1.xpro_value, "on");
  187.                 else
  188.                     strcpy(opti1.xpro_value, "off");
  189.             }
  190.             opti2.xpro_value = AllocMem(4, MEMF_PUBLIC);
  191.             if (opti2.xpro_value) {
  192.                 if (IO->xpr_data->big)
  193.                     strcpy(opti2.xpro_value, "on");
  194.                 else
  195.                     strcpy(opti2.xpro_value, "off");
  196.             }
  197.             opti3.xpro_value = AllocMem(4, MEMF_PUBLIC);
  198.             if (opti3.xpro_value) {
  199.                 if (IO->xpr_data->ascii)
  200.                     strcpy(opti3.xpro_value, "on");
  201.                 else
  202.                     strcpy(opti3.xpro_value, "off");
  203.             }
  204.  
  205.             callad(xoptions, &opti, IO->xpr_finfo?3:4);
  206.  
  207.             if (
  208.                    (!strcmp(opti1.xpro_value, "yes")) ||
  209.                    (!strcmp(opti1.xpro_value, "on"))
  210.                 )
  211.                 IO->xpr_data->crc_conf = 1;
  212.             else
  213.                 IO->xpr_data->crc_conf = 0;
  214.  
  215.             if (
  216.                    (!strcmp(opti2.xpro_value, "yes")) ||
  217.                    (!strcmp(opti2.xpro_value, "on"))
  218.                 )
  219.                 IO->xpr_data->big = 1;
  220.             else
  221.                 IO->xpr_data->big = 0;
  222.  
  223.             if (
  224.                    (!strcmp(opti3.xpro_value, "yes")) ||
  225.                    (!strcmp(opti3.xpro_value, "on"))
  226.                 )
  227.                 IO->xpr_data->ascii = 1;
  228.             else
  229.                 IO->xpr_data->ascii = 0;
  230.  
  231.             if (opti3.xpro_value)
  232.                 FreeMem(opti3.xpro_value, 4);
  233.             if (opti2.xpro_value)
  234.                 FreeMem(opti2.xpro_value, 4);
  235.             if (opti1.xpro_value)
  236.                 FreeMem(opti1.xpro_value, 4);
  237.         } else {
  238.             sprintf(buffy, "T%d,C%d,K%d", IO->xpr_data->ascii, IO->xpr_data->crc_conf, IO->xpr_data->big);
  239.             callaa(xgets, "Enter XModem config string (A<0|1>,C<0|1>,K<0|1>)", buffy);
  240.             ParseConfigString(IO, buffy);
  241.         }
  242.     } else
  243.         ParseConfigString(IO, IO->xpr_filename);
  244.  
  245.     return (1);
  246. }
  247.  
  248. void PutCH(struct XPR_IO * IO, int ch)
  249. {
  250.     long (*xfwrite) ();
  251.  
  252.     if ((xfwrite = IO->xpr_fwrite) == NULL)
  253.         return;
  254.  
  255.     if (IO->xpr_data->savech == '\032')
  256.         return;
  257.  
  258.     if (IO->xpr_data->savech == '\r') {
  259.         if (ch != '\n') {
  260.             unsigned char blou = IO->xpr_data->savech;
  261.  
  262.             calladda(xfwrite, &blou, 1, 1, (void *) IO->xpr_data->fp);
  263.         }
  264.         IO->xpr_data->savech = 0;
  265.     }
  266.     if (IO->xpr_data->ascii) {
  267.         if (ch == '\r' || ch == '\032')
  268.             IO->xpr_data->savech = ch;
  269.         else {
  270.             unsigned char blou = ch;
  271.  
  272.             calladda(xfwrite, &blou, 1, 1, (void *) IO->xpr_data->fp);
  273.         }
  274.     } else {
  275.         unsigned char blou = ch;
  276.  
  277.         calladda(xfwrite, &blou, 1, 1, (void *) IO->xpr_data->fp);
  278.     }
  279. }
  280.  
  281. int GetCH(struct XPR_IO * IO)
  282. {
  283.     unsigned char chc;
  284.     int ch;
  285.     long (*xfread) ();
  286.  
  287.     if ((xfread = IO->xpr_fread) == NULL)
  288.         return (0L);
  289.  
  290.     if (IO->xpr_data->savech) {
  291.         ch = IO->xpr_data->savech;
  292.         IO->xpr_data->savech = 0;
  293.     } else {
  294.         if (!calladda(xfread, &chc, 1, 1, (void *) IO->xpr_data->fp))
  295.             ch = EOF;
  296.         else
  297.             ch = (int) chc;
  298.  
  299.         if (IO->xpr_data->ascii) {
  300.             if (ch == '\n') {
  301.                 IO->xpr_data->savech = ch;
  302.                 ch = '\r';
  303.             } else if (ch == EOF) {
  304.                 IO->xpr_data->savech = EOF;
  305.                 ch = '\032';
  306.             }
  307.         }
  308.     }
  309.     return (ch);
  310. }
  311.  
  312. void SerialTransparent(struct XPR_IO * IO)
  313. {
  314.     if (IO->xpr_setserial) {
  315.         IO->xpr_data->serialbits = calld(IO->xpr_setserial, -1);
  316.         calld(IO->xpr_setserial, ((IO->xpr_data->serialbits) & ~(1 + 2 + 64 + 256 + 1024 + 2048 + 4096)) | 128);
  317.     }
  318. }
  319.  
  320. void SerialRestore(struct XPR_IO * IO)
  321. {
  322.     if (IO->xpr_setserial)
  323.         calld(IO->xpr_setserial, IO->xpr_data->serialbits);
  324. }
  325.  
  326. long XProtocolSend(struct XPR_IO * IO)
  327. {
  328.     long brkflag = 0, size=0, oldascii;
  329.     long (*xupdate) (), (*xswrite) (), (*xfopen) (), (*xfclose) (),
  330.      (*xfread) (), (*xsread) (), (*xfinfo) (), (*xchkabort) (void);
  331.     struct XPR_UPDATE xpru;
  332.  
  333.     if ((xupdate = IO->xpr_update) == NULL)
  334.         return (0L);
  335.     if ((xswrite = IO->xpr_swrite) == NULL)
  336.         return (0L);
  337.     if ((xfopen = IO->xpr_fopen) == NULL)
  338.         return (0L);
  339.     if ((xfclose = IO->xpr_fclose) == NULL)
  340.         return (0L);
  341.     if ((xfread = IO->xpr_fread) == NULL)
  342.         return (0L);
  343.     if ((xsread = IO->xpr_sread) == NULL)
  344.         return (0L);
  345.     if ((xchkabort = IO->xpr_chkabort) == NULL)
  346.         return (0L);
  347.  
  348.     oldascii=IO->xpr_data->ascii;
  349.  
  350.     if(xfinfo = IO->xpr_finfo) {
  351.         size = callad(xfinfo, IO->xpr_filename, 1);    /* get file size */
  352.         switch(callad(xfinfo, IO->xpr_filename, 2)) {    /* get file type */
  353.             case 1: IO->xpr_data->ascii=0; break; /* Binary */
  354.             case 2: IO->xpr_data->ascii=1; break; /* Text */
  355.             default: break; /* uh? */
  356.         }
  357.     }
  358.  
  359.     IO->xpr_data->fp = callaa(xfopen, IO->xpr_filename, "r");
  360.     if (!IO->xpr_data->fp) {
  361.         xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_FILENAME;
  362.         xpru.xpru_errormsg = "Failed to open input file";
  363.         xpru.xpru_filename = IO->xpr_filename;
  364.         calla(xupdate, &xpru);
  365.         IO->xpr_data->ascii=oldascii;
  366.         return (0L);
  367.     }
  368.     /* Initialize display */
  369.     bm_infoinit(IO, 1, size);
  370.  
  371.     SerialTransparent(IO);
  372.  
  373.     if (!dl_snd(IO, GetCH))
  374.         brkflag = 2;
  375.  
  376.     SerialRestore(IO);
  377.  
  378.     if (IO->xpr_data->abort == 1)
  379.         brkflag = 1;
  380.  
  381.     calla(xfclose, (void *) IO->xpr_data->fp);
  382.  
  383.     xpru.xpru_updatemask = XPRU_MSG;
  384.     switch (brkflag) {
  385.     case 0:
  386.         xpru.xpru_msg = "Done";
  387.         break;
  388.     case 1:
  389.         xpru.xpru_msg = "Aborted";
  390.         break;
  391.     case 2:
  392.         xpru.xpru_msg = "Failed";
  393.         break;
  394.     }
  395.     calla(xupdate, &xpru);
  396.  
  397.     IO->xpr_data->ascii=oldascii;
  398.  
  399.     if (brkflag)
  400.         return (0);
  401.     else
  402.         return (1);
  403. }
  404.  
  405. long XProtocolReceive(struct XPR_IO * IO)
  406. {
  407.     long brkflag = 0, oldascii;
  408.     long (*xupdate) (), (*xswrite) (), (*xfopen) (), (*xfclose) (),
  409.      (*xfwrite) (), (*xsread) (), (*xfinfo) ();
  410.     struct XPR_UPDATE xpru;
  411.  
  412.     if ((xupdate = IO->xpr_update) == NULL)
  413.         return (0L);
  414.     if ((xswrite = IO->xpr_swrite) == NULL)
  415.         return (0L);
  416.     if ((xfopen = IO->xpr_fopen) == NULL)
  417.         return (0L);
  418.     if ((xfclose = IO->xpr_fclose) == NULL)
  419.         return (0L);
  420.     if ((xfwrite = IO->xpr_fwrite) == NULL)
  421.         return (0L);
  422.     if ((xsread = IO->xpr_sread) == NULL)
  423.         return (0L);
  424.  
  425.     oldascii=IO->xpr_data->ascii;
  426.  
  427.     if(xfinfo = IO->xpr_finfo) switch(callad(xfinfo, IO->xpr_filename, 2)) {    /* get file type */
  428.         case 1: IO->xpr_data->ascii=0; break; /* Binary */
  429.         case 2: IO->xpr_data->ascii=1; break; /* Text */
  430.         default: break; /* uh? */
  431.     }
  432.  
  433.     IO->xpr_data->fp = callaa(xfopen, IO->xpr_filename, "w");
  434.     if (IO->xpr_data->fp == NULL) {
  435.         xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_FILENAME;
  436.         xpru.xpru_errormsg = "Failed to open output file";
  437.         xpru.xpru_filename = IO->xpr_filename;
  438.         calla(xupdate, &xpru);
  439.         IO->xpr_data->ascii=oldascii;
  440.         return (0L);
  441.     }
  442.     IO->xpr_data->savech = 0;
  443.  
  444.     /* Initialize display */
  445.     bm_infoinit(IO, 0, 0);
  446.  
  447.     SerialTransparent(IO);
  448.  
  449.     if (!dl_rcv(IO, PutCH))
  450.         brkflag = 2;
  451.  
  452.     SerialRestore(IO);
  453.  
  454.     if (IO->xpr_data->abort == 1)
  455.         brkflag = 1;
  456.  
  457.     /*
  458.      * Close the file
  459.      */
  460.     calla(xfclose, (void *) IO->xpr_data->fp);
  461.  
  462.     xpru.xpru_updatemask = XPRU_MSG;
  463.     switch (brkflag) {
  464.     case 0:
  465.         xpru.xpru_msg = "Done";
  466.         break;
  467.     case 1:
  468.         xpru.xpru_msg = "Aborted";
  469.         break;
  470.     case 2:
  471.         xpru.xpru_msg = "Failed";
  472.         break;
  473.     }
  474.  
  475.     calla(xupdate, &xpru);
  476.  
  477.     IO->xpr_data->ascii=oldascii;
  478.  
  479.     if (brkflag) {
  480.         long (*xsflush)(void);
  481.  
  482.         if (xsflush = IO->xpr_sflush) xsflush();
  483.         return (0);
  484.     } else return (1);
  485. }
  486.  
  487. /**
  488. *
  489. *   The following is stuff replacing mdio.c
  490. *
  491. **/
  492.  
  493. /*
  494.  * md_get - get a character from the modem with timeout
  495.  */
  496. int md_get(struct XPR_IO * IO, int tmo)
  497. {
  498.     int ch;
  499.     unsigned char chc;
  500.     long howmany;
  501.     long (*xchkabort) (void);
  502.  
  503.     xchkabort = IO->xpr_chkabort;
  504.  
  505.     if (xchkabort())
  506.         if (!IO->xpr_data->abort)
  507.             IO->xpr_data->abort = 1;
  508.  
  509.     if (IO->xpr_data->abort) {
  510.         calladd(IO->xpr_sread, &chc, 1, 1);
  511.         return (DT_ERR);
  512.     }
  513.     howmany = calladd(IO->xpr_sread, &chc, 1, tmo * 1000000L);
  514.     ch = chc;
  515.  
  516.     if (!howmany)
  517.         return (DT_TIME);
  518.     return (ch);
  519. }
  520.  
  521. /*
  522.  * md_put - output a character to the modem
  523.  */
  524. void md_put(struct XPR_IO * IO, int ch)
  525. {
  526.     unsigned char chc = ch;
  527.  
  528.     callad(IO->xpr_swrite, &chc, 1);
  529. }
  530.  
  531. /*
  532.  * md_write - write a packet to the modem
  533.  */
  534. void md_write(struct XPR_IO * IO, char *buf, int len)
  535. {
  536.     callad(IO->xpr_swrite, buf, len);
  537. }
  538.